﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.Corp;
using Modules.Project.Entitys;
using Modules.Project.Repositories;
using Pipelines.Sockets.Unofficial.Arenas;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Exceptions;
using static Modules.Person.PersonConstants;

namespace Modules.Project
{
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectCorpService
    {
        private readonly ProjectCorpRepository projectCorpRepository;
        private readonly ProjectGroupService projectGroupService;
        private readonly CorpService corpService;
        private readonly IApplicationContext applicationContext;
        private readonly ILogger logger;
        private readonly ProjectAttachmentService projectAttachmentService;
        private readonly ProjectGroupMemberService projectGroupMemberService;

        public ProjectCorpService(
            ProjectCorpRepository projectCorpRepository,
            ProjectGroupService projectGroupService,
            IApplicationContext applicationContext,
            ILogger<ProjectCorpService> logger,
            CorpService corpService,
            ProjectAttachmentService projectAttachmentService,
            ProjectGroupMemberService projectGroupMemberService
            )
        {
            this.projectCorpRepository = projectCorpRepository;
            this.projectGroupService = projectGroupService;
            this.applicationContext = applicationContext;
            this.logger = logger;
            this.corpService = corpService;
            this.projectAttachmentService = projectAttachmentService;
            this.projectGroupMemberService = projectGroupMemberService;
        }

        /// <summary>
        /// 创建承建单位（不存在需要创建建设单位的情况）
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="corpInfo"></param>
        /// <param name="attachments"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateProjectCorp(ProjectCorp entity, CorpInfo? corpInfo, List<string> attachments)
        {
            if (projectCorpRepository.ExistsByProjectCorp(entity))
                throw new BusinessException($"项目已存在所选参建单位，不能再次创建");
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                //需要创建企业信息
                if (corpInfo != null)
                {
                    corpService.CreateCorpInfoNoTransaction(corpInfo);
                    entity.CorpId = corpInfo.CorpId;
                }
                //创建承建单位关联
                projectCorpRepository.Insert(entity);
                //创建附件关联
                foreach (var item in attachments)
                {
                    ProjectAttachment projectCorpAttachment = new()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", ""),
                        AttachmentId = item,
                        ObjectId = entity.Id.ToString(),
                        Tenant = 项目附件租户.ProjectCorp,
                        AttachmentType = 附件类型.参建单位合同,
                        CreateTime = DateTime.Now
                    };
                    projectAttachmentService.Create(projectCorpAttachment);
                }

                #region 新增管理组

                projectGroupService.SilentCreateProjectGroup(new ProjectGroup()
                {
                    ProjectId = entity.ProjectId,
                    CorpId = entity.CorpId,
                    Name = "项目部班组",
                    //IsProjectManager = true,
                    CreateTime = DateTime.Now,
                    StartDate = entity.StartDate,
                    EndDate = entity.EndDate,
                    IsManagerGroup = true
                });

                #endregion 新增管理组

                applicationContext.Transaction.Complete();//完成事务
            }
            catch (BusinessException ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                throw new BusinessException(ex.Message);
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateProjectCorp Exception ProjectId:{entity.ProjectId}");
                throw new BusinessException("新增承建单位失败");
            }
        }

        /// <summary>
        /// 创建承建单位（不存在需要创建建设单位的情况）
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="corpInfo"></param>
        /// <param name="attachments"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateProjectCorpNoTransaction(ProjectCorp entity, CorpInfo? corpInfo = null, List<string>? attachments = null, bool addManage = true)
        {
            if (projectCorpRepository.ExistsByProjectCorp(entity))
                throw new BusinessException($"项目Id：{entity.ProjectId} 和企业Id {entity.CorpId} 已存在，不能创建");

            //需要创建企业信息
            if (corpInfo != null)
            {
                corpService.CreateCorpInfoNoTransaction(corpInfo);
                entity.CorpId = corpInfo.CorpId;
            }
            //创建承建单位关联
            projectCorpRepository.Insert(entity);
            //创建附件关联

            if (attachments != null)
            {
                foreach (var item in attachments)
                {
                    ProjectAttachment projectCorpAttachment = new()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", ""),
                        AttachmentId = item,
                        ObjectId = entity.Id.ToString(),
                        Tenant = 项目附件租户.ProjectCorp,
                        AttachmentType = 附件类型.参建单位合同,
                        CreateTime = DateTime.Now
                    };
                    projectAttachmentService.Create(projectCorpAttachment);
                }
            }

            #region 新增管理组

            if (addManage)
            {
                projectGroupService.CreateProjectGroup(new ProjectGroup()
                {
                    ProjectId = entity.ProjectId,
                    CorpId = entity.CorpId,
                    Name = "项目部班组",
                    CreateTime = DateTime.Now,
                    StartDate = entity.StartDate,
                    EndDate = entity.EndDate,
                    IsManagerGroup = true
                });
            }

            #endregion 新增管理组
        }

        /// <summary>
        /// 批量创建或更新
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="inProjectCorps"></param>
        //public void CreateOrUpdate(int projectId, IEnumerable<ProjectCorp> inProjectCorps)
        //{
        //    projectCorpRepository.CreateOrUpdate(projectId, inProjectCorps);
        //}

        public void DeleteProjectCorp(int id)
        {
            projectCorpRepository.DeleteByEntityId(id);
        }

        public void DeletedProjectCorps(IEnumerable<int> ids)
        {
            //判断当前参建单位下面是否有工人在场，若有工人在场，则不能删除
            IEnumerable<ProjectCorp> ProjectCorps = GetProjectCorps(ids);

            foreach (var item in ProjectCorps)
            {
                IEnumerable<ProjectGroupMember> projectGroupMembers = projectGroupMemberService.GetProjectGroupMembersByProjectId(item.ProjectId).Where(a => a.CorpId == item.CorpId);
                if (projectGroupMembers.Any())
                {
                    throw new BusinessException("选择的参建单位中还有人员在场，暂时不能删除");
                }

                //删除班组信息
                var projectGroupService = applicationContext.GetService<ProjectGroupService>();
                IEnumerable<ProjectGroup> projectGroups = projectGroupService.GetProjectGroupsByProjectId(item.ProjectId).Where(a => a.CorpId == item.CorpId);

                try
                {
                    applicationContext.Transaction.Begin();

                    //删除参建企业
                    DeleteProjectCorp(item.Id);

                    //遍历删除所有班组
                    foreach (var projectGroup in projectGroups)
                    {
                        projectGroupService.DeleteProjectGroup(projectGroup.GroupId);
                    }

                    applicationContext.Transaction.Complete();
                }
                catch (BusinessException)
                {
                    applicationContext.Transaction.Abort();
                    throw new BusinessException("选择的参建单位中还有人员在场，暂时不能删除");
                }
                catch (Exception ex)
                {
                    applicationContext.Transaction.Abort();
                    throw new BusinessException($"删除参建单位失败：{ex.Message}");
                }
            }

            applicationContext.Transaction.Complete();
        }

        public IEnumerable<ProjectCorp> GetProjectCorpsByCorpId(int corpId)
        {
            return projectCorpRepository.GetProjectCorpsByCorpId(corpId);
        }

        public IEnumerable<ProjectCorp> GetProjectCorpsByProjectId(int projectId)
        {
            return projectCorpRepository.GetProjectCorpsByProjectId(projectId);
        }

        public ProjectCorp? GetProjectCorp(int id)
        {
            return projectCorpRepository.Get(id);
        }

        public IEnumerable<ProjectCorp> GetProjectCorps(IEnumerable<int> ids)
        {
            return projectCorpRepository.PopulateEntitiesByEntityIds(ids);
        }

        public ProjectCorp? GetProjectCorpByProjectIdAndCorpId(int projectId, int corpId)
        {
            var projectCorps = GetProjectCorpsByProjectId(projectId);
            return projectCorps.FirstOrDefault(m => m.CorpId == corpId);
        }

        public IPagedList<ProjectCorp> GetProjectCorps(ProjectCorpQuery query, int pageNum, int pageSize)
        {
            return projectCorpRepository.GetProjectCorps(query, pageNum, pageSize);
        }

        /// <summary>
        /// 修改承建单位信息
        /// </summary>
        /// <param name="entity">参建企业信息</param>
        /// <param name="corpInfo">企业信息</param>
        /// <param name="attachments"></param>
        /// <exception cref="BusinessException"></exception>
        public void UpdateProjectCorp(ProjectCorp entity, CorpInfo corpInfo, List<string> attachments)
        {
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                if (projectCorpRepository.ExistsByProjectCorp(entity, entity.Id))
                    throw new BusinessException($"项目Id：{entity.ProjectId} 和企业Id {entity.CorpId} 已存在，不能创建");
                //需要创建企业信息
                if (corpInfo.CorpId <= 0)
                {
                    corpService.CreateCorpInfoNoTransaction(corpInfo);
                    entity.CorpId = corpInfo.CorpId;
                }
                //修改承建单位关联
                projectCorpRepository.Update(entity);
                //创建附件关联
                var ids = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(entity.Id, 附件类型.参建单位合同, 项目附件租户.ProjectCorp).Select(i => i.Id).ToList();
                projectAttachmentService.Deleted(ids);
                foreach (var item in attachments)
                {
                    ProjectAttachment projectCorpAttachment = new()
                    {
                        Id = Guid.NewGuid().ToString("N"),
                        AttachmentId = item,
                        ObjectId = entity.Id.ToString(),
                        Tenant = 项目附件租户.ProjectCorp,
                        AttachmentType = 附件类型.参建单位合同,
                        CreateTime = DateTime.Now
                    };
                    projectAttachmentService.Create(projectCorpAttachment);
                }
                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"UpdateProjectCorp Exception ProjectId:{entity.ProjectId}");
                throw new BusinessException("修改承建单位失败");
            }
        }

        public void Update(ProjectCorp entity)
        {
            projectCorpRepository.Update(entity);
        }

        public object Insert(ProjectCorp entity)
        {
            return projectCorpRepository.Insert(entity);
        }

        public bool ExistsProjectCorp(int projectId, int corpId, 项目参建单位类型 role)
        {
            return projectCorpRepository.ExistsProjectCorp(projectId, corpId, role);
        }
    }
}